//
//  VersionManager.swift
//  ToBeBigFE
//
//  Created by mingo on 2020/3/5.
//  Copyright © 2020 com.example. All rights reserved.
//

import Foundation
import Alamofire

// manifest更新错误
enum ManifestError : Error {
    case responseBodyEmpty
    case parseError
}

// manifest更新的callback定义
typealias ManifestUpdatedCallback = (_ error: ManifestError?) -> Void

class VersionManager {
    
    private let userDefaults: UserDefaults
    private let manifestKey = "web.manifest"
    // 项目名 => 版本
    private var builtinDict = [String:String]()
    private var versionDict = [String:String]()
    
    // 防止重复调用的标识
    private var manifestUpdating = false
    // 重复调用时的callback数组
    private var manifestUpdateCallbacks = [ManifestUpdatedCallback]()
    
    init(userDefaults: UserDefaults) {
        self.userDefaults = userDefaults
        
        // 读取解析manifest.json的过程
        let path = Bundle.main.path(forResource: "manifest", ofType: "json")!
        let data = FileManager.default.contents(atPath: path)!
        try! parseManifest(data, output: &builtinDict)
        builtinDict.forEach {
            versionDict[$0.key] = $0.value
        }
        
        // 解析userDefaults里更新到的
        if let manifestData = userDefaults.data(forKey: manifestKey) {
            try? parseManifest(manifestData, output: &versionDict)
        }
    }
    
    func getVersion(id: String) -> String? {
        return versionDict[id]
    }
    
    func getBuiltinVersion(id: String) -> String? {
        return builtinDict[id]
    }
    
    func updateManifest(callback: @escaping ManifestUpdatedCallback) {
        if (manifestUpdating) {
            manifestUpdateCallbacks.append(callback)
            return
        }

        print("WebManager update manifest")

        manifestUpdating = true
        manifestUpdateCallbacks.append(callback)
        
        let callbackAll = { (error: ManifestError?) in
            print("WebManager update manifest complete")
            self.manifestUpdateCallbacks.forEach { callback in
                callback(error)
            }
            self.manifestUpdateCallbacks.removeAll()
            self.manifestUpdating = false
        }
        
        // 下面使用Alamofire请求manifest
        let url = "\(WebConst.WEB_BASE_URL)manifest.json?t=\(Int64(Date().timeIntervalSince1970))"
        AF.request(url).responseData { resp in
            guard let data = resp.data else {
                callbackAll(.responseBodyEmpty)
                return
            }
            do {
                try self.parseManifest(data, output: &self.versionDict)
                self.userDefaults.set(data, forKey: self.manifestKey)
            } catch {
                callbackAll(.parseError)
                return
            }
            callbackAll(nil)
        }
    }
    
    private func parseManifest(_ data: Data, output: inout [String:String]) throws {
        let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String:Any?]
        let projects = json["projects"] as! [[String:Any?]]
        projects.forEach { item in
            output[item["name"] as! String] = item["version"] as? String
        }
    }
}
